import { Injectable } from '@angular/core'
import { Validators, FormGroup } from '@angular/forms'
import { FieldBase } from './field-base.interface'
import { HiddenField } from './field-hidden.interface'
import { NumberField } from './field-number.interface'
import { MCCSelectField } from './field-mcc.interface'
import { MCCType } from '@shared/components/mcc-select/mcc-select.interface'
import { GroupField } from './field-group.interface'
import {
  ICardChannelMasterCard,
  ICardChannelVisa,
  ICardChannelAmex,
  ICardChannelUpi,
} from '@shared/interfaces/acquirer'
import { IStoreCardChanMer, ICardRouteOfStore } from '@shared/interfaces/store'
import { ChanMerSelectField } from './field-chan-mer-select.interface'
import { TextboxField } from './field-textbox.interface'
import { SelectField } from './field-select.interface'
import { EPaymentBrand } from '@shared/enums'
import { IMCC } from '@shared/components/mcc-select/mcc-select.interface'
import {
  alphanumericReg,
  onlyNumberReg,
  alphanumericAndSymbolsReg,
  addressMaxLength,
  chanNameMaxLength,
} from 'app/utils/contraints'
import { MetaData } from '@shared/interfaces/store'
import { I18NService } from '@core'

@Injectable()
export class ChannelFormCardService {
  constructor(private i18n: I18NService) {}

  getVisaChannelFields(val?: ICardRouteOfStore): FieldBase<any>[] {
    let selectedChanMer: ICardChannelVisa = null
    let cmp: IStoreCardChanMer
    console.log('getVisaChannelFields: ', val)
    if (val && val.chanMerParams) {
      cmp = val.chanMerParams as IStoreCardChanMer
      selectedChanMer = {
        id: val.chanMerObjId,
        paymentBrand: EPaymentBrand.Visa,
        chanCode: EPaymentBrand.Visa,
        offlineInsCode: cmp.offlineInsCode,
        bin: cmp.bin,
        chanMerID: cmp.offlineInsCode,
        chanMerName: '',
      }
    }

    if (val.mccNameEN && (val.mcc as IMCC)) {
      val.mcc = {
        mccEnName: val.mccNameEN,
        mccCode: val.mcc as string,
      }
    }
    const fields: FieldBase<any>[] = [
      new GroupField(
        {
          key: 'chanMerParams',
          order: 1,
        },
        [
          new ChanMerSelectField({
            key: 'selectedChanMer',
            label: 'Institution Code in Offline System',
            value: selectedChanMer,
            labelKeyOfOption: 'offlineInsCode',
            validators: [Validators.required],
            validatorErrors: {
              required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'Institution Code in Offline System' }),
            },
            options: [],
            compareWith: (o1: any, o2: any) => (o1 && o2 ? o1.id === o2.id : o1 === o2),
            onModelChange: (value: ICardChannelMasterCard, form: FormGroup) => {
              form.get('bin').setValue(value ? value.bin : null)
            },
            disabled: !!(val && val.id),
          }),
          new TextboxField({
            key: 'bin',
            label: 'BIN',
            disabled: true,
            value: (cmp && cmp.bin) || '',
          }),
        ],
      ),
      new MCCSelectField({
        key: 'mcc',
        label: 'Visa MCC',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'Visa MCC' }),
        },
        value: val && val.mcc ? (val.mcc as IMCC) : undefined,
        mccType: MCCType.Visa,
        order: 2,
      }),
      new NumberField({
        key: 'fee',
        label: 'Transaction Fee',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Fee' }),
        },
        value: val.fee,
        order: 3,
      }),
      new SelectField({
        key: 'currency',
        label: 'Channel transaction currency',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'Channel transaction currency' }),
        },
        value: (val && val.currency) || undefined,
        options: [],
        order: 5,
      }),
    ]

    return fields
  }

  getMasterCardChannelFields(val?: ICardRouteOfStore): FieldBase<any>[] {
    let selectedChanMer: ICardChannelMasterCard = null
    let cmp: IStoreCardChanMer
    if (val && val.chanMerParams) {
      cmp = val.chanMerParams as IStoreCardChanMer
      selectedChanMer = {
        id: val.chanMerObjId,
        bin: cmp.bin,
        ica: cmp.ica,
        paymentBrand: EPaymentBrand.Visa,
        chanCode: EPaymentBrand.Visa,
        offlineInsCode: cmp.offlineInsCode,
        chanMerID: cmp.offlineInsCode,
        chanMerName: '',
      }
    }

    if (val.mccNameEN && (val.mcc as IMCC)) {
      val.mcc = {
        mccEnName: val.mccNameEN,
        mccCode: val.mcc as string,
      }
    }

    const fields: FieldBase<any>[] = [
      new GroupField(
        {
          key: 'chanMerParams',
          order: 1,
        },
        [
          new ChanMerSelectField({
            key: 'selectedChanMer',
            label: 'Institution Code in Offline System',
            value: selectedChanMer,
            validators: [Validators.required],
            validatorErrors: {
              required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'Institution Code in Offline System' }),
            },
            labelKeyOfOption: 'offlineInsCode',
            options: [],
            compareWith: (o1: any, o2: any) => (o1 && o2 ? o1.id === o2.id : o1 === o2),
            onModelChange: (value: ICardChannelMasterCard, form: FormGroup) => {
              form.get('bin').setValue(value ? value.bin : null)
              form.get('ica').setValue(value ? value.ica : null)
            },
            disabled: !!(val && val.id),
          }),
          new TextboxField({
            key: 'bin',
            label: 'BIN',
            disabled: true,
            value: (cmp && cmp.bin) || '',
          }),
          new TextboxField({
            key: 'ica',
            label: 'ICA',
            disabled: true,
            value: (cmp && cmp.ica) || '',
          }),
        ],
      ),
      new MCCSelectField({
        key: 'mcc',
        label: 'MasterCard MCC',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'MasterCard MCC' }),
        },
        value: val && val.mcc ? (val.mcc as IMCC) : undefined,
        mccType: MCCType.MasterCard,
        order: 2,
      }),
      new NumberField({
        key: 'fee',
        label: 'Transaction Fee',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Fee' }),
        },
        value: val.fee,
        order: 3,
      }),
      new SelectField({
        key: 'currency',
        label: 'Channel transaction currency',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'Channel transaction currency' }),
        },
        value: (val && val.currency) || undefined,
        options: [],
        order: 4,
      }),
    ]

    return fields
  }

  getAmexChannelFields(val?: ICardRouteOfStore, metaData?: MetaData): FieldBase<any>[] {
    let selectedChanMer: ICardChannelAmex = null
    let cmp: IStoreCardChanMer
    if (val && val.chanMerParams) {
      cmp = val.chanMerParams as IStoreCardChanMer
      selectedChanMer = {
        id: val.chanMerObjId,
        paymentBrand: EPaymentBrand.AME,
        chanCode: EPaymentBrand.AME,
        ain: cmp.ain,
        first3DigitsOfSENumber: cmp.first3DigitsOfSENumber,
      }
    }

    if (val.mccNameEN && (val.mcc as IMCC)) {
      val.mcc = {
        mccEnName: val.mccNameEN,
        mccCode: val.mcc as string,
      }
    }

    const fields: FieldBase<any>[] = [
      new GroupField(
        {
          key: 'chanMerParams',
          order: 1,
        },
        [
          new ChanMerSelectField({
            key: 'selectedChanMer',
            label: 'AIN',
            value: selectedChanMer,
            labelKeyOfOption: 'ain',
            validators: [Validators.required],
            validatorErrors: {
              required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'AIN' }),
            },
            options: [],
            compareWith: (o1: any, o2: any) => (o1 && o2 ? o1.id === o2.id : o1 === o2),
            onModelChange: (value: ICardChannelAmex, form: FormGroup) => {
              form.get('first3DigitsOfSENumber').setValue(value ? value.first3DigitsOfSENumber : null)
            },
            disabled: !!(val && val.id),
          }),
          new TextboxField({
            key: 'first3DigitsOfSENumber',
            label: 'First 3 digits of S/E Number',
            disabled: true,
            value: (cmp && cmp.first3DigitsOfSENumber) || '',
          }),
        ],
      ),
      new TextboxField({
        key: 'chanNameEN',
        label: 'Store English Name',
        validators: [
          Validators.required,
          Validators.maxLength(chanNameMaxLength),
          Validators.pattern(alphanumericAndSymbolsReg),
        ],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Store English Name' }),
          maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: chanNameMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.ALPHANUMERIC_ONLY'),
        },
        value: (metaData && metaData.chanNameEN) || (val && val.chanNameEN) || '',
        order: 2,
      }),
      new TextboxField({
        key: 'chanAddrEN',
        label: 'Store English Address',
        validators: [
          Validators.required,
          Validators.maxLength(addressMaxLength),
          Validators.pattern(alphanumericAndSymbolsReg),
        ],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Store English Address' }),
          maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: addressMaxLength }),
          pattern: this.trans('VALIDATION.PATTERN.ALPHANUMERIC_ONLY'),
        },
        value: (metaData && metaData.chanAddrEN) || (val && val.chanAddrEN) || '',
        order: 2,
      }),
      new MCCSelectField({
        key: 'mcc',
        label: 'American Express MCC',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'American Express MCC' }),
        },
        value: val && val.mcc ? (val.mcc as IMCC) : undefined,
        mccType: MCCType.MasterCard,
        order: 2,
      }),
      new NumberField({
        key: 'fee',
        label: 'Transaction Fee',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED', { name: 'Transaction Fee' }),
        },
        value: val.fee,
        order: 3,
      }),
      new SelectField({
        key: 'currency',
        label: 'Channel transaction currency',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'Channel transaction currency' }),
        },
        value: (val && val.currency) || undefined,
        options: [],
        order: 4,
      }),
    ]

    return fields
  }

  getUpiChannelFields(val?: ICardRouteOfStore, metaData?: MetaData): FieldBase<any>[] {
    let selectedChanMer: ICardChannelUpi = null
    let cmp: IStoreCardChanMer
    if (val && val.chanMerParams) {
      cmp = val.chanMerParams as IStoreCardChanMer
      selectedChanMer = {
        id: val.chanMerObjId,
        paymentBrand: EPaymentBrand.AME,
        chanCode: EPaymentBrand.AME,
        ain: cmp.ain,
        fin: cmp.fin,
      }
    }

    if (val.mccNameEN && (val.mcc as IMCC)) {
      val.mcc = {
        mccEnName: val.mccNameEN,
        mccCode: val.mcc as string,
      }
    }

    const fields: FieldBase<any>[] = [
      new GroupField(
        {
          key: 'chanMerParams',
          order: 1,
        },
        [
          new ChanMerSelectField({
            key: 'selectedChanMer',
            label: this.trans('GENERAL.INFO.CHANNEL.UPI_ACQUIRING_IIN'),
            value: selectedChanMer,
            labelKeyOfOption: 'ain',
            validators: [Validators.required],
            validatorErrors: {
              required: this.trans('VALIDATION.REQUIRED_SELECT', {
                name: this.trans('GENERAL.INFO.CHANNEL.UPI_ACQUIRING_IIN'),
              }),
            },
            options: [],
            compareWith: (o1: any, o2: any) => (o1 && o2 ? o1.id === o2.id : o1 === o2),
            onModelChange: (value: ICardChannelUpi, form: FormGroup) => {
              form.get('fin').setValue(value ? value.fin : null)
            },
            disabled: !!(val && val.id),
          }),
          new TextboxField({
            key: 'fin',
            label: this.trans('GENERAL.INFO.CHANNEL.UPI_FOWARDING_IIN'),
            disabled: true,
            value: (cmp && cmp.fin) || '',
          }),
        ],
      ),
      new MCCSelectField({
        key: 'mcc',
        label: 'UPI MCC',
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED_SELECT', { name: 'UPI MCC' }),
        },
        value: val && val.mcc ? (val.mcc as IMCC) : undefined,
        mccType: MCCType.MasterCard,
        order: 2,
      }),
      new NumberField({
        key: 'fee',
        label: this.trans('GENERAL.INFO.TRANSACTION_FEE'),
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.INFO.TRANSACTION_FEE') }),
        },
        value: val.fee,
        order: 3,
      }),
      new SelectField({
        key: 'currency',
        label: this.trans('CARD.GENERAL.INFO.TRANSACTION_CURRENCY'),
        validators: [Validators.required],
        validatorErrors: {
          required: this.trans('VALIDATION.REQUIRED_SELECT', { name: this.trans('GENERAL.INFO.TRANSACTION_CURRENCY') }),
        },
        value: (val && val.currency) || undefined,
        options: [],
        order: 4,
      }),
    ]

    return fields
  }
  private trans(str: string, params?: Object): string {
    return this.i18n.fanyi(str, params)
  }
}
